#
# Package.
#

package iSOCK::Controller::Specification::Compare;

#
# Parent.
#

use Moose;
use namespace::autoclean;

BEGIN { extends 'iSOCK::Controller::Root' }

#
# Uses.
#

use File::Slurp qw( slurp );
use JSON;
use SOCK::BOT qw( x_to_y_hash_as_lol );
use SOCK::LOG;
use Sort::Naturally qw( nsort );

#
# Documentation.
#

=head1 NAME

iSOCK::Controller::Compare - Product Controller for iSOCK

=head1 DESCRIPTION

[enter your description here]

=head1 METHODS

=cut

#
# Subs.
#

sub index :Path :Args(0) {
  my ( $self, $c ) = @_;

  my $parameters = $c->request->parameters;

  if ( $c->request->method eq 'POST' && $parameters->{form_specifications_compare} ) {
    if ( my $session = $c->session ) {
      my $session_id   = $c->sessionid;
      my $session_path = $self->session_path ( $c );
      
      my $log = SOCK::LOG->new ({ file => "$session_path/isock_product.log", fatality => 0 });
            
      $log->say_n_right ( "Processing within $session_id session..." );

      my ( @options, $checked );
      
      for ( nsort grep { ! m/-/ && ! m/form_specifications_compare/ } keys %$parameters ) {
        $checked->{$_} = 1;
        
        my $option = "--product $_";
        
        my $tag = "$_-tag";
        if ( exists $parameters->{$tag} && $parameters->{$tag} ne '-' ) {
          $option .= "=$parameters->{$tag}";
        }
        
        push @options, $option;
      }
      
      if ( $checked ) {
        $c->response->cookies->{'isock-specification-compare-products'} = { value => join ( ',', nsort keys %$checked ), expires => '+3M' };
      }
      
      $c->model ( 'Product' )->vs_product ({ options => "@options", c => $c, log => $log });
      
      if ( -f "$session_path/sock_product_vs_product.json" ) {
        my $json = decode_json ( slurp ( "$session_path/sock_product_vs_product.json" ) );
        
        $c->stash (
          checked => $checked,
          tables  => [ map { {
            id    => $_->{id},
            table => _x_to_y_hash_as_html_table_string ( $json->{$_->{id}}, sub { $_[0] || '-' }, {
              id      => $_->{id},
              class   => 'sortable',
              caption => $_->{caption},
          } ) } } (
            { id => 'instance_address',         caption => 'Product to instance address'             },
            { id => 'component_version',        caption => 'Product to component version'            },
            { id => 'component_variable_sha1',  caption => 'Product to component variable SHA1 sum'  },
            { id => 'component_condition_sha1', caption => 'Product to component condition SHA1 sum' },
          ) ],
        );
      }
            
      $log->left_n_say ( "Done." );
      
      $log->close;
    }
  }
  elsif ( my $cookie = $c->request->cookies->{'isock-specification-compare-products'} ) {
    my $checked;
       $checked->{$_} = 1 for split ',', $cookie->value;
    
    if ( $checked ) {
      $c->stash ( checked => $checked );
    }
  }
  
  $c->stash ( specifications => $c->model ( 'App' )->specifications_loh ( $c ) );

  $c->forward ( qw( iSOCK::Controller::Root render_view ) );
}

sub _x_to_y_hash_as_html_table_string : Private {
  my ( $hash, $sub, $option ) = @_;
  
  $sub ||= sub { return $_[0] ? 'X' : '-' };
  
  _lol_as_html_table_string ( x_to_y_hash_as_lol ( $hash, $sub ), $option );
}

sub _lol_as_html_table_string : Private {
  my ( $lol, $option ) = @_;
    
  my ( $head, @bodies ) = @$lol;
  
  my $html;
  
  $html .= "<table" . ( $option->{id} ? " id=\"$option->{id}\"" : "" ) . " " . ( $option->{class} ? " class=\"$option->{class}\"" : "" ) . ">\n";

  $html .= "  <caption>$option->{caption}</caption>\n" if $option->{caption};

  $html .= "  <thead>\n";
  $html .= "    <tr>\n";
  $html .= join '', map {
        "      <th>$_</th>\n";
  } @$head;
  $html .= "    </tr>\n";
  $html .= "  </thead>\n";

  $html .= "  <tbody>\n";
  $html .=
    "    <tr>\n" . join ( '', map {
    "      <td>$_</td>\n" } @$_ ) .
    "    </tr>\n" for @bodies;
  $html .= "  </tbody>\n";

  $html .= "</table>\n";
  
  $html;
}

#
# Documentation.
#

=head1 AUTHOR

Xavier Caron

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

#
# End of iSOCK::Controller::Specification::Compare.
#

1;
